package com.example.socket.socket.nio;

import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Set;

public class ChartClient {

    private static final String DEFULT_SERVER_HOST="127.0.0.1";

    private static final int DEFUT_SERVER_PORT=88889;

    private static final String QUIT="quit";

    private static final int BUFFER=1024;

    private String host;

    private int port;

    private SocketChannel client;

    //选择器
    private Selector selector;

    //用来读取消息
    private ByteBuffer rBuffer=ByteBuffer.allocate(BUFFER);
    //用来写入信息
    private ByteBuffer wBeBuffer=ByteBuffer.allocate(BUFFER);


    private Charset charset=Charset.forName("UTF-8");

    public void start(){
        try {
            client=SocketChannel.open();
            client.configureBlocking(false);
            selector= Selector.open();
            client.register(selector,SelectionKey.OP_CONNECT);
            client.connect(new InetSocketAddress(host,port));
            while (true){
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey selectionKey : selectionKeys) {
                    handles(selectionKey);
                }
                selectionKeys.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            close(selector);
        }
    }

    private void handles(SelectionKey selectionKey) throws IOException {
        //CONNECT事件---连接就绪事件
        if (selectionKey.isConnectable()){
            SocketChannel client = (SocketChannel) selectionKey.channel();
            //请求是否已经链接
            if(client.isConnectionPending()){
                //正式建立链接
                client.finishConnect();
                new Thread(new UserInputHandler(this)).start();
            }
            client.register(selector,SelectionKey.OP_READ);
        }
        //REDE事件---服务器转发事件
        else if(selectionKey.isReadable()){
           SocketChannel client= (SocketChannel) selectionKey.channel();
           String msg=receive(client);
           if(msg.isEmpty()){
               //服务器异常
               close(selector);
           }else{
               System.out.println(msg);
           }
        }
    }

    private String receive(SocketChannel client) throws IOException {
        rBuffer.clear();
        while (client.read(rBuffer)>0);
        rBuffer.flip();
        return String.valueOf(charset.decode(rBuffer));
    }

    public ChartClient(){
        this(DEFULT_SERVER_HOST,DEFUT_SERVER_PORT);
    }
    public ChartClient(String host, int port){
       this.host=host;
       this.port=port;
    }

    public boolean readyToQuit(String msg){
        return QUIT.equals(msg);
    }

    public void send(String msg) throws IOException {
        if(msg.isEmpty()){
            return;
        }
        wBeBuffer.clear();
        wBeBuffer.put(charset.encode(msg));
        wBeBuffer.flip();
        while (wBeBuffer.hasRemaining()){
            client.write(wBeBuffer);
        }
        //检查用户是否准备推出
        if(readyToQuit(msg)){
            close(selector);
        }
    }

    public void close(Closeable closeable){
        if(closeable!=null){
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ChartClient chartClient=new ChartClient("127.0.0.1",8886);
        chartClient.start();
    }
}
